/*
 *
 *   Copyright (C) 2005 by Raymond Huang
 *   plushuang at users.sourceforge.net
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  ---
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of portions of this program with the
 *  OpenSSL library under certain conditions as described in each
 *  individual source file, and distribute linked combinations
 *  including the two.
 *  You must obey the GNU Lesser General Public License in all respects
 *  for all of the code used other than OpenSSL.  If you modify
 *  file(s) with this exception, you may extend this exception to your
 *  version of the file(s), but you are not obligated to do so.  If you
 *  do not wish to do so, delete this exception statement from your
 *  version.  If you delete this exception statement from all source
 *  files in the program, then also delete it here.
 *
 */

#ifndef __BASE_NODE_H
#define __BASE_NODE_H

#include <glib.h>
#include <urlglib/urlglib_signal.h>
#include <urlglib/conf_writer.h>
#include <urlglib/conf_parser.h>

// Hierarchy :
//
// GNode
// |
// `---BaseNode
//     |
//     +--- RootNode
//     |
//     +--- CategoryNode
//     |
//     +--- QueueNode
//     |
//     +--- DownloadNode
//     |
//     `--- ProxyNode
//

//
// Run-time tree struct :
//
// RootNode
// |
// +--- CategoryNode instance 1
// |    |
// |    +--- QueueNode instance 1 (waiting queue)
// |    |    |
// |    |    +--- DownloadNode instance 1
// |    |    |    |
// |    |    |    +--- ProxyNode instance 1
// |    |    |    |
// |    |    |    `--- ProxyNode instance 2
// |    |    |
// |    |    `--- DownloadNode instance 2
// |    |         |
// |    |         `--- ProxyNode instance 3
// |    |
// |    +--- QueueNode instance 2 (completed queue)
// |    |    |
// |    |    ...
// |    |
// |    `--- QueueNode instance 3 (recycled queue)
// |         |
// |         ...
// |
// `--- CategoryNode instance 2
//      |
//      ...
//

#ifdef __cplusplus
extern "C" {
#endif

#define BASE_NODE(obj)             ((BaseNode*)(obj))

#define BASE_NODE_FIELDS              \
	GNode                 gnode;      \
	BaseNodeFinalizeFunc  finalize;   \
	int        reference_count;       \
	GSList*    inserted_signal;       \
	GSList*    removed_signal

typedef struct _BaseNode             BaseNode;
typedef struct _BaseNodeSignalData   BaseNodeSignalData;
typedef void (*BaseNodeFinalizeFunc) (BaseNode* node);
typedef void (*BaseNodeCallback) (BaseNode* parent, BaseNode* child, int nth, gpointer data);

struct _BaseNode {
    BASE_NODE_FIELDS;
};

void base_node_instance_init     (BaseNode* node);
void base_node_instance_finalize (BaseNode* node);

void base_node_ref   (BaseNode* node);
void base_node_unref (BaseNode* node);

#define base_node_prev(node)            (BaseNode*) g_node_prev_sibling ((GNode*)(node))
#define base_node_next(node)            (BaseNode*) g_node_next_sibling ((GNode*)(node))
#define base_node_parent(node)          (BaseNode*) ((GNode*)(node))->parent
#define base_node_first_child(node)     (BaseNode*) g_node_first_child ((GNode*)(node))
#define base_node_last_child(node)      (BaseNode*) g_node_last_child ((GNode*)(node))
#define base_node_nth_child(node,n)     (BaseNode*) g_node_nth_child ((GNode*)(node),n)

#define base_node_child                 base_node_first_child
#define base_node_child_position(parent, child)    \
            g_node_child_position((GNode*)(parent), (GNode*)(child))
#define base_node_n_children(node)      g_node_n_children ((GNode*)(node))

void base_node_insert_before (BaseNode* parent, BaseNode* sibling, BaseNode* node);
void base_node_insert_after  (BaseNode* parent, BaseNode* sibling, BaseNode* node);

void base_node_append (BaseNode* parent, BaseNode* node);
void base_node_prepend (BaseNode* parent, BaseNode* node);
void base_node_unlink (BaseNode* node);

// callback & setup

void base_node_signal_emit_full (GSList** signal_list, BaseNode* parent, BaseNode* child, int nth);
#define base_node_signal_emit(sl, p, c)  base_node_signal_emit_full(sl,p,c,-1)

#define base_node_inserted_connect(node, fn, data)    \
            urlglib_signal_connect (&(node)->inserted_signal, fn, data)
#define base_node_removed_connect(node, fn, data)     \
            urlglib_signal_connect (&(node)->removed_signal, fn, data)
#define base_node_inserted_disconnect(node, sig)    \
            urlglib_signal_disconnect (&(node)->inserted_signal, sig)
#define base_node_removed_disconnect(node, sig)     \
            urlglib_signal_disconnect (&(node)->removed_signal, sig)

#define base_node_inserted(node, child)    \
            base_node_signal_emit (&(node)->inserted_signal, node, child)
#define base_node_removed(node, child, nth)     \
            base_node_signal_emit_full (&(node)->removed_signal, node, child, nth)

#ifdef __cplusplus
}
#endif

#endif  // End of __BASE_NODE_H
